package com.cxs.musicplaywidget.player.store;

import com.cxs.musicplaywidget.player.data.AVBaseMeta;
import com.cxs.musicplaywidget.player.data.MusicData;
import com.cxs.musicplaywidget.player.data.MusicInfo;
import com.cxs.musicplaywidget.util.LogUtils;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.bundle.IBundleManager;
import ohos.data.resultset.ResultSet;
import ohos.media.photokit.metadata.AVMetadataHelper;
import ohos.media.photokit.metadata.AVStorage;
import ohos.security.SystemPermission;
import ohos.utils.net.Uri;
import ohos.utils.zson.ZSONArray;
import ohos.utils.zson.ZSONException;
import ohos.utils.zson.ZSONObject;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.PatternSyntaxException;

public class MediaStore {
    private static final String tag = MediaStore.class.getSimpleName();
    private volatile static MediaStore instance = null;
    private final Context context;
    private static List<MusicInfo> musicList = null;

    private MediaStore(Context context) {
        this.context = context;
    }

    public static MediaStore getInstance(Context context) {
        if (instance == null) {
            synchronized (MediaStore.class) {
                if (instance == null) {
                    instance = new MediaStore(context);
                }
            }
        }
        return instance;
    }

    /**
     * Get audio files
     * @return
     */
    private ResultSet queryAvStore() {
        ResultSet resultSet = null;
        DataAbilityHelper helper = DataAbilityHelper.creator(context);
        try {
            resultSet = helper.query(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, null, null);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
        return resultSet;
    }

    public List<MusicInfo> getMedia(boolean reload) {
        if (reload) {
            return getMedia();
        }
        return musicList;
    }

    /**
     * Get the Music List
     * @return
     */
    public List<MusicInfo> getMedia() {
        if (context.verifySelfPermission(SystemPermission.READ_MEDIA)!= IBundleManager.PERMISSION_GRANTED) {
            return null;
        }
        ResultSet resultSet = queryAvStore();
        musicList = new ArrayList<>();
        int i = 0;
        while (resultSet.goToNextRow()) {
            String path = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DATA));
            // 根据文件名获取歌手和歌名
            String musicId = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.ID));
            String mimeType = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.MIME_TYPE));
            String duration = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DURATION));
            String displayName = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DISPLAY_NAME));
            AVBaseMeta baseMeta = new AVBaseMeta(musicId, getMusicInfo(displayName), mimeType, getIntDuration(duration));
            MusicInfo metadata = getMetadata(baseMeta, path);

            if (isMP3(duration)) {
                LogUtils.debug(tag, "getMedia.metadata=" + metadata);
                metadata.setIndex(i);
                musicList.add(metadata);
                i++;
            }
        }
        return musicList;
    }


    /**
     * get audio metadata
     * @param path
     * @return
     */
    private MusicInfo getMetadata(AVBaseMeta baseMeta, String path) {
        AVMetadataHelper avMetadataHelper = new AVMetadataHelper();
        avMetadataHelper.setSource(path);
        MusicInfo musicInfo = new MusicInfo();
        musicInfo.setPath(path);
        musicInfo.setMusicId(baseMeta.getMusicId());
        // name
        musicInfo.setName(baseMeta.getInfo().name);
        // title
        String title = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_TITLE);
        if (title == null) {
            musicInfo.setTitle(baseMeta.getInfo().title);
        } else {
            musicInfo.setTitle(title);
        }
        // album
        String album = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_ALBUM);
        musicInfo.setAlbum(album);
        // author
        String author = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_AUTHOR);
        musicInfo.setAuthor(author);
        // artist
        String artist = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_ARTIST);
        if (artist == null) {
            musicInfo.setArtist(baseMeta.getInfo().artist);
        } else {
            musicInfo.setArtist(artist);
        }
        // mimeType
        String mimeType = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_MIMETYPE);
        if (mimeType == null) {
            musicInfo.setMimeType(baseMeta.getMimeType());
        } else {
            musicInfo.setMimeType(mimeType);
        }
        // duration
        String duration = avMetadataHelper.resolveMetadata(AVMetadataHelper.AV_KEY_DURATION);
        if (duration == null) {
            musicInfo.setDuration(baseMeta.getDuration());
        } else {
            musicInfo.setDuration(getIntDuration(duration));
        }
        avMetadataHelper.release();
        return musicInfo;
    }

    private MusicBaseInfo getMusicInfo(String fileName) {
        if (fileName == null) {
            return null;
        }
        String f = fileName.substring(0, fileName.lastIndexOf("."));
        try {
            String[] split = f.split("-", 2);
            if (split.length == 2) {
                return new MusicBaseInfo(split[0], split[1], fileName);
            }
        } catch (PatternSyntaxException e) {
        }
        return new MusicBaseInfo(f, "未知歌手", fileName);
    }
    public class MusicBaseInfo {
        public String title;
        public String artist;
        public String name;

        public MusicBaseInfo(String title, String artist, String name) {
            this.title = title;
            this.artist = artist;
            this.name = name;
        }
    }

    /**
     * Convert a string duration to an integer
     * @param duration
     * @return
     */
    private int getIntDuration(String duration) {
        try {
            int i = Integer.parseInt(duration);
            return i;
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * 是否是mp3
     * @param duration
     * @return
     */
    private boolean isMP3(String duration) {
        if (duration == null) {
            return false;
        }
        if (Long.parseLong(duration) > 60000) {
            return true;
        }
        return false;
    }

    /**
     * 获取歌曲的数据流
     * @param musicInfo
     * @return
     */
    public MusicData getMusicData(MusicInfo musicInfo) {
        if (musicInfo == null) {
            return null;
        }
        FileInputStream fis = null;
        try {
            Uri uri = Uri.appendEncodedPathToUri(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, musicInfo.getMusicId() );
            DataAbilityHelper abilityHelper = DataAbilityHelper.creator(context);
            FileDescriptor fileDescriptor = abilityHelper.openFile(uri, "r");
            fis = new FileInputStream(fileDescriptor);
            int total = fis.available();  //文件总长度
            byte[] bytes = new byte[total];
            // 返回读取到的数据长度
            int len = fis.read(bytes);
            MusicData musicData = new MusicData(total);
            musicData.writeData(bytes);
            return musicData;
        }catch (IOException | IllegalStateException | DataAbilityRemoteException e) {
            LogUtils.debug(tag, "getMusicData failed " + e.getMessage());
            return null;
        }finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public byte[] getThumbnail(String musicId) {
        try {
            AVMetadataHelper avMetadataHelper = new AVMetadataHelper();
            Uri uri = Uri.appendEncodedPathToUri(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, musicId );
            DataAbilityHelper abilityHelper = DataAbilityHelper.creator(context);
            FileDescriptor fileDescriptor = abilityHelper.openFile(uri, "r");

            //通过文件描述符获取封面
            avMetadataHelper.setSource(fileDescriptor);
            byte[] bytes = avMetadataHelper.resolveImage();
            avMetadataHelper.release();
            return bytes;
        }catch (IllegalStateException | DataAbilityRemoteException | FileNotFoundException e) {
            LogUtils.debug(tag, "getThumbnail failed " + e.getMessage());
            return null;
        }
    }

    public byte[] getThumbnail(MusicInfo musicInfo) {
        return getThumbnail(musicInfo.getMusicId());
    }
}

